﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using WBoy.WeixinCore;
using WBoy.WeixinCore.Exceptions;
using WeixinPayWeb.Models;

namespace WeixinPayWeb.Controllers
{
    [Route("api/Pay")]
    [ApiController]
    public class PayController : ControllerBase
    {
        private readonly WeixinPayHelper _weixinPayHelper;

        public PayController()
        {
            _weixinPayHelper = new WeixinPayHelper("", "", "", "");
        }
        /// <summary>
        /// 获取订单支付的前面实体
        /// </summary>
        /// <param name="orderId"></param>
        /// <returns></returns>
        [HttpGet]
        [LoginAuth] //去实现登录验证不能随意提交
        [Route("GetOrderSign")]
        public ResultMessage GetOrderSign(string orderId)
        {
            try
            {
                //to do 直接实现获取校验订单的 业务方法


                //开始微信支付校验过程

                var transactionId = orderId;// 交易号必须每次支付订单都不一样
                var transactionDescribe = "测试交易订单";//订单描述信息
                var payAmount = (decimal)0.01;// 单位元 支付金额由服务端设置 不能使用通过客户端传过来的值 防止用户自己修改
                var dicParams = new Dictionary<string, string>//自定义数据 回调中传回来
                {
                    {"orderId", orderId}
                };

                #region 调用微信支付服务器创建订单

                var passbackParams = HttpUtility.UrlEncode(JsonHelper.SerializeV2(dicParams, true), Encoding.UTF8);

                var parameters = new Dictionary<string, string>
                {
                    {"appid", _weixinPayHelper.AppId},
                    {"mch_id", _weixinPayHelper.MchId},
                    {"out_trade_no",transactionId},
                    {"body", transactionDescribe},
                    {"spbill_create_ip", "127.0.0.1"},
                    {"notify_url", _weixinPayHelper.NotifyUrl},
                    //JSAPI--JSAPI支付（或小程序支付）、NATIVE--Native支付、APP--app支付，MWEB--H5支付，不同trade_type决定了调起支付的方式，请根据支付产品正确上传
                    {"trade_type", "JSAPI"},// App 表示APP交易类型  H5支付的交易类型为MWEB 
                    {"nonce_str", Guid.NewGuid().ToString().Replace("-", null)},
                    {"total_fee", ((int)(payAmount*100)).ToString()},//微信支付 单位是分
                    { "attach",passbackParams}

                };
                var sign = _weixinPayHelper.CreateSign(parameters);
                parameters.Add("sign", sign);
                var xml = _weixinPayHelper.ParseXml(parameters);
                var request = new WebRequestHelper();
                var wxResponseXml = request.RequestPostDataUrl(WexinPayUrl.unifiedorder, xml);
                if (wxResponseXml == "")
                {
                    return new ResultMessage(StateCode.Fail, "微信服务器未响应");
                }

                #endregion

                #region 进行第二次前面 返回支付参数给客户端 客户端使用返回参数去支付

                //支付订单结果转换成Dictionary
                var dictResult = _weixinPayHelper.XmlToDictionary(wxResponseXml);
                if (dictResult["return_code"] == "FAIL")
                {
                    return new ResultMessage(StateCode.Fail, dictResult["return_msg"]);
                }
                //to do 容易报错 用测试服务多测试
                if (dictResult["return_code"] == "SUCCESS" && dictResult["result_code"] == "FAIL")
                {
                    if (dictResult.ContainsKey("err_code_des") && dictResult["err_code_des"] == "商户订单号重复")
                    {
                        return new ResultMessage(StateCode.Fail, "订单号重复，请您重新支付！");
                    }
                    return new ResultMessage(StateCode.Fail, "创建订单错误，请您重新支付！");
                }
                var prepayId = dictResult["prepay_id"];
                TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
                var timestamp = Convert.ToInt64(ts.TotalSeconds).ToString();
                var package = "Sign=WXPay";
                var noncestr = Guid.NewGuid().ToString().Replace("-", "");
                var hashtable = new Dictionary<string, string>
                {
                    {"appid", _weixinPayHelper.AppId},
                    {"partnerid", _weixinPayHelper.MchId},
                    {"prepayid", prepayId},
                    {"package", package},
                    {"noncestr", noncestr},
                    {"timestamp", timestamp}
                };
                sign = _weixinPayHelper.CreateSign(hashtable);

                var responseModel = new WeiXinPayResponseModel(_weixinPayHelper.AppId, _weixinPayHelper.MchId, prepayId, package, noncestr, timestamp, sign, transactionId, payAmount);

                return new ResultMessage<WeiXinPayResponseModel>(responseModel, "成功获取支付信息");

                #endregion

            }
            catch (WeixinException e)
            {
                return new ResultMessage(StateCode.Fail, e.Message);
            }
        }
        /// <summary>
        /// 微信支付成功回调函数
        /// </summary>
        [Route("notify")]
        [HttpPost]
        public ActionResult<string> Notify()
        {
            //读取返回的xml
            //StreamReader reader = new StreamReader(HttpContext.Current.Request.InputStream);
            //var xmlData = reader.ReadToEnd();
            var reader = new StreamReader(HttpContext.Request.Body);
            var xmlData = reader.ReadToEnd();
            HostLogHelper.AddLog("开始微信支付回调 接受数据:" + xmlData);
            //LoggerFactory.CreateLog().LogInfo("开始微信支付回调 接受数据：{0}", xmlData);
            StringBuilder resultSb = new StringBuilder();
            try
            {
                var dict = _weixinPayHelper.XmlToDictionary(xmlData);
                //验证签名错误
                if (!_weixinPayHelper.CheckSign(dict))
                {
                    HostLogHelper.AddLog("微信验证签名失败 return_msg：{0}", dict["return_msg"]);
                    //LoggerFactory.CreateLog().LogInfo("微信验证签名失败 return_msg：{0}", dict["return_msg"]);
                    return ResponseMessage(HttpStatusCode.InternalServerError, "fail");
                }

                //回调出错信息
                if (dict["result_code"] == "FAIL")
                {
                    HostLogHelper.AddLog("微信支付回调结果code失败 return_msg：{0}", dict["return_msg"]);
                    //LoggerFactory.CreateLog().LogInfo("微信支付回调结果code失败 return_msg：{0}", dict["return_msg"]);
                    return ResponseMessage(HttpStatusCode.InternalServerError, "fail");
                }
                //处理订单
                var attach = HttpUtility.UrlDecode(dict["attach"], Encoding.UTF8);
                HostLogHelper.AddLog("微信支付交易成功，交易流水号:{0}订单号:{1} 支付金额:{2},附加参数：{3}", dict["transaction_id"], dict["out_trade_no"], float.Parse(dict["total_fee"]) / 100, attach);
                var dic = WBoy.WeixinCore.JsonHelper.Deserialize<Dictionary<string, string>>(attach);
                var orderType = dic["orderType"];
                var orderId = dic["orderId"];
                
                return ResponseMessage(HttpStatusCode.OK, "success");
            }
            catch (WeixinException ex)
            {
                HostLogHelper.AddLog("支付发送异常：{0}", ex.Message);
                return ResponseMessage(HttpStatusCode.InternalServerError, "fail");
            }
        }
        private string ResponseMessage(HttpStatusCode statusCode, string message)
        {
            HttpContext.Response.StatusCode = (int) statusCode;
            return message;
        }
    }
}